package com.liao.domain.strategy.service;

import com.liao.domain.strategy.model.entity.RaffleAwardEntity;
import com.liao.domain.strategy.model.entity.RaffleFactorEntity;
import com.liao.domain.strategy.model.entity.RuleActionEntity;
import com.liao.domain.strategy.model.entity.StrategyAwardEntity;
import com.liao.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
import com.liao.domain.strategy.model.valobj.StrategyAwardRuleModelVO;
import com.liao.domain.strategy.repository.IStrategyRepository;
import com.liao.domain.strategy.service.armory.IStrategyDispatch;
import com.liao.domain.strategy.service.rule.chain.ILogicChain;
import com.liao.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import com.liao.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import com.liao.types.enums.ResponseCode;
import com.liao.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;

/*
 * @Author:  long
 * @Description: 抽奖策略抽象类，定义抽奖的标准流程
 * @date:  2024-08-03 14:47
 */
@Slf4j
public abstract class AbstractRaffleStrategy implements IRaffleStrategy {

    @Resource
    protected IStrategyRepository strategyRepository;
    @Resource
    private IStrategyDispatch strategyDispatch;
    @Resource
    protected DefaultChainFactory defaultChainFactory;
    @Resource
    protected DefaultTreeFactory defaultTreeFactory;

    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {

        String userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();

        if (StringUtils.isBlank(userId) || strategyId == null) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        //责任链处理前置抽奖
//        ILogicChain logicChain = defaultChainFactory.openLogicChain(strategyId);
//        Long awardId = logicChain.logic(userId, strategyId);

        DefaultChainFactory.StrategyAwardVO chainStrategyAwardVO = raffleLogicChain(userId, strategyId);
        log.info("抽奖策略计算-责任链 {} {} {} {}", userId, strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getLogicModel());
        //不是默认规则，直接返回奖品
        if (!DefaultChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAwardVO.getLogicModel())) {
            return buildRaffleAwardEntity(strategyId, chainStrategyAwardVO.getAwardId(), null);
        }

        DefaultTreeFactory.StrategyAwardVO treeStrategyAwardVO = raffleLogicTree(userId, strategyId, chainStrategyAwardVO.getAwardId());
        log.info("抽奖策略计算-规则树 {} {} {} {}", userId, strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());
        //返回抽奖结果
        return buildRaffleAwardEntity(strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());
    }

    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId, Long awardId, String awardConfig) {
        StrategyAwardEntity strategyAward = strategyRepository.queryStrategyAwardEntity(strategyId, awardId);
        return RaffleAwardEntity.builder()
                .awardId(awardId)
                .awardConfig(awardConfig)
                .sort(strategyAward.getSort())
                .build();
    }

    /**
     * 抽奖计算，责任链抽象方法
     *
     * @param userId     用户ID
     * @param strategyId 策略ID
     * @return 奖品ID
     */
    public abstract DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId);

    /**
     * 抽奖结果过滤，决策树抽象方法
     *
     * @param userId     用户ID
     * @param strategyId 策略ID
     * @param awardId    奖品ID
     * @return 过滤结果【奖品ID，会根据抽奖次数判断、库存判断、兜底兜里返回最终的可获得奖品信息】
     */
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Long awardId);

}
